package GUI;

import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;

import user.User;
import controller.ImageLoader;
import controller.LoginManager;
import controller.LocalManager;

public class TopLevelFrame extends JFrame{
	public TopLevelFrame(){
		this.user = LoginManager.getCurrentLogged();
    	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    	this.setTitle("My GDR");
    	this.setSize(new Dimension(900, 700));
    	this.setLocation(350, 150);
    	displayed = null;
		setDispleyedPanel(createMenu());
		ResizeListener resizeListener = new ResizeListener();
		this.addComponentListener(resizeListener);
		
		new Thread(new Runnable() {
			public void run() {
				ImageLoader.load();
			}
		}).start();
	}
	
	public JPanel createMenu(){
		JPanel panel = new JPanel();
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		Dimension size = TopLevelFrame.this.getSize();
		panel.setPreferredSize(new Dimension(size.width-100, size.height-100));
		
		//box to chose the game to load
		final JPanel saveBox = new JPanel(new BorderLayout());
		final DefaultListModel<String> listModel = new DefaultListModel<String>();
		for(String savedGame: LocalManager.getAll())
			listModel.addElement(savedGame);
		final JList<String> listedSaves = new JList<String>(listModel);
		listedSaves.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		listedSaves.setLayoutOrientation(JList.VERTICAL);
		//listedSaves.addListSelectionListener();
		listedSaves.setSelectedIndex(-1);
		JScrollPane savesScr = new JScrollPane(listedSaves);
		savesScr.setPreferredSize(new Dimension(120, 200));
		JButton confirmLoad = new JButton("OK");
		confirmLoad.addActionListener(new LoadListener(listedSaves));
		JButton delete = new JButton("Cancella");
		delete.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				int index = listedSaves.getSelectedIndex();
				if(index != -1){
					LocalManager.delete(listedSaves.getSelectedValue());
				    listModel.remove(index);
				    int size = listModel.getSize();
				    if (size == 0) { //Nobody's left, disable deleting.
				    	saveBox.setVisible(false);
				    	load.setEnabled(false);
				    } else {
				        listedSaves.setSelectedIndex(-1);
				    }
				}
			}
		});
		JPanel p = new JPanel();
		p.setOpaque(false);
		p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
		p.add(Box.createHorizontalGlue());
		p.add(delete);
		p.add(Box.createRigidArea(new Dimension(10, 0)));
		p.add(confirmLoad);
		saveBox.setOpaque(true);
		saveBox.setBackground(new Color(180, 180, 180));
		saveBox.setVisible(false);
		saveBox.add(savesScr, BorderLayout.CENTER);
		saveBox.add(p, BorderLayout.SOUTH);
		
		//buttons
		JLabel title = new JLabel("My GDR");
		title.setFont(new Font("Title", Font.BOLD, 30));
		title.setAlignmentX(CENTER_ALIGNMENT);
		start = new JButton("Avvia avventura");
		start.setAlignmentX(CENTER_ALIGNMENT);
		start.addActionListener(new NewGame());
		load = new JButton("Carica avventura");
		load.setAlignmentX(CENTER_ALIGNMENT);
		load.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(saveBox.isVisible()){
					saveBox.setVisible(false);
				}else{
					saveBox.setVisible(true);
				}
				saveBox.revalidate();
			}
		});
		if(listModel.getSize() == 0)
			load.setEnabled(false);
		JButton exit = new JButton("Esci");
		exit.setAlignmentX(CENTER_ALIGNMENT);
		exit.addActionListener(new ExitListener());
		
		//progress bar to image loading
		final JProgressBar loading = new JProgressBar();
		loading.setMaximum(5);
		loading.setAlignmentX(CENTER_ALIGNMENT);
		loading.setValue(0);
		loading.setStringPainted(true);
		new Thread(new Runnable() {
			public void run() {
				ImageLoader.addNotifyListener(this);
				while(!ImageLoader.isLoaded()){
					synchronized (this) {
						try {
							this.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					loading.setValue(loading.getValue()+1);
					TopLevelFrame.this.revalidate();
				}
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				loading.setVisible(false);
			}
		}).start();
		
		//create panel
		panel.add(Box.createRigidArea(new Dimension(0, 40)));
		panel.add(title);
		panel.add(Box.createRigidArea(new Dimension(0, 40)));
		panel.add(start);
		panel.add(Box.createRigidArea(new Dimension(0, 20)));
		panel.add(load);
		panel.add(Box.createRigidArea(new Dimension(0, 10)));
		panel.add(saveBox);
		panel.add(Box.createRigidArea(new Dimension(0, 10)));
		panel.add(exit);
		panel.add(Box.createVerticalGlue());
		panel.add(loading);
		return panel;
	}
	
	public void createGamePanel(){
		try {
			SwingUtilities.invokeAndWait(new Runnable() {
				public void run() {
					start.setEnabled(false);
					load.setEnabled(false);
					addMenuBar();
					Dimension size = TopLevelFrame.this.getContentPane().getSize();
					setDispleyedPanel(new GamePanel(TopLevelFrame.this, false, new Dimension(size.width, size.height-20)));
				}
			});
		} catch (InvocationTargetException | InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public void addMenuBar(){
    	JMenuBar menu = new JMenuBar();
        JMenu file = new JMenu("File");
        JMenuItem save = new JMenuItem("Save");
        JMenuItem exit = new JMenuItem("Exit");
        save.addActionListener(new SaveListener());
        exit.addActionListener(new ExitListener());
        exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0));
        save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
        file.add(save);
        file.add(exit);
        menu.add(file);
        setJMenuBar(menu);
    }
	
	public void setDispleyedPanel(JComponent c){
		if(displayed != null)
			this.remove(displayed);
		this.add(c);
		displayed = c;
		this.revalidate();
	}
	
	public class NewGame implements ActionListener{
        public void actionPerformed(ActionEvent e) {
        	new Thread(){
        		public void run() {
        			setDispleyedPanel(new NewGamePanel(TopLevelFrame.this));
        		};
        	}.start();
        }
    }
	
	/*
	public class NewGameDinamic implements ActionListener{
        public void actionPerformed(ActionEvent e) {
        	new Thread(){
        		public void run() {
        			start.setEnabled(false);
        			load.setEnabled(false);
        			ImageLoader.addNotifyListener(this);
        			while(!ImageLoader.isLoaded()){
        				synchronized (this) {
        					try {
        						this.wait();
        					} catch (InterruptedException ex) {
        						ex.printStackTrace();
        					}
        				}
        			}
                	if(overlayedPanel != null)
        				TopLevelFrame.this.getLayeredPane().remove(overlayedPanel);
        			//create new map
        			final ArrayList<Object> exit = new ArrayList<Object>();
        			final Map m = MapGenerator.nextDinamic(24, 30, 5, exit); //to do creation effect
        			LocalManager.setMap(m);
        			LocalManager.setCurrentMission(null); //it will be (re)created
        			mission = null;
        			while(exit.size() == 0){
        				map = new MapPanel(currentRes);
        				map.addMouseWheelListener(new MouseWheel());
        				refreshMapAndMissionPanel();
        				synchronized (MapGenerator.class) {
        					try {
        						MapGenerator.class.wait();
        					} catch (InterruptedException ex) {
        						ex.printStackTrace();
        					}
        				}
        			}
        			// set player location
        			int i=0, j=0;
        			boolean trovato = false;
        			for(i = 0; i<m.getWidth() && !trovato; i++)
        				for(j = 0; j<m.getHeight() && !trovato; j++)
        					if(m.getTexture(i, j) == Texture.CITY)
        						trovato = true;
        			if(trovato)
        				LocalManager.setPlayerLocation(new Point(i-1, j-1));
        			else
        				LocalManager.setPlayerLocation(new Point(m.getWidth()/2, m.getHeight()/2));
        			
        			//create panel mission and other gui
        			mission = new MissionPanel(currentRes, TopLevelFrame.this, TopLevelFrame.this);
        			mission.addMouseWheelListener(new MouseWheel());
        			refreshMapAndMissionPanel();
        			addMenuBar();
        			addOverlayButtonsPanel();
        		}
        	}.start();
        }
    }
	*/
	
	public class LoadListener implements ActionListener{
		public LoadListener(JList<String> listedSaves){
			this.listedSaves = listedSaves;
		}
        public void actionPerformed(ActionEvent e) {
			new Thread(){
				public void run() {
					if(listedSaves.getSelectedIndex() != -1){
						start.setEnabled(false);
	        			load.setEnabled(false);
						ImageLoader.addNotifyListener(this);
						while(!ImageLoader.isLoaded()){
							synchronized (this) {
								try {
									this.wait();
								} catch (InterruptedException ex) {
									ex.printStackTrace();
								}
							}
						}
			        	//load map, mission and player
						boolean result = LocalManager.load(listedSaves.getSelectedValue());
						if(result){
							Dimension size = TopLevelFrame.this.getContentPane().getSize();
							setDispleyedPanel(new GamePanel(TopLevelFrame.this, true, new Dimension(size.width, size.height)));
						}else{
							setDispleyedPanel(createMenu());
						}
					}
				}
			}.start();
        }
        private JList<String> listedSaves;
    }
	
	class ResizeListener implements ComponentListener{
    	public void componentResized(ComponentEvent e) {
			Dimension size = TopLevelFrame.this.getContentPane().getSize();
			displayed.setPreferredSize(new Dimension(size.width, size.height));
			displayed.revalidate();
		}
		public void componentMoved(ComponentEvent e) {}
		public void componentHidden(ComponentEvent e) {}
		public void componentShown(ComponentEvent e) {}
    }
	
	public class SaveListener implements ActionListener{
        public void actionPerformed(ActionEvent e) {
            LocalManager.save();
            
        }
    }

    public class ExitListener implements ActionListener{
        public void actionPerformed(ActionEvent e) {
            System.exit(0);
        }
    }
	
    private JButton load, start;
	private JComponent displayed;
	private User user;
	private static final long serialVersionUID = -308899976L;
	
	public static void main(String[] args){
        JFrame f = new TopLevelFrame();
        f.setVisible(true);
    }
}
